package com.zenithmind.user.controller;

import com.zenithmind.common.annotation.Log;
import com.zenithmind.common.constant.OperationTypeEnum;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.user.controller.base.BaseController;
import com.zenithmind.user.enums.VerificationCodeType;
import com.zenithmind.user.pojo.dto.AdminLoginDTO;
import com.zenithmind.user.pojo.dto.LoginDTO;
import com.zenithmind.user.pojo.dto.RegisterDTO;
import com.zenithmind.user.pojo.dto.SimpleLoginDTO;
import com.zenithmind.user.pojo.dto.VerificationRequestDTO;
import com.zenithmind.user.pojo.vo.UserVO;
import com.zenithmind.user.service.domain.AuthenticationService;
import com.zenithmind.user.service.domain.UserManagementService;
import com.zenithmind.user.service.VerificationCodeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

/**
 * 认证控制器
 * 遵循单一职责原则：专门处理用户认证相关功能
 * 遵循开闭原则：通过策略模式支持多种认证方式
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/auth")
@RequiredArgsConstructor
@Tag(name = "用户认证", description = "用户登录、注册、登出等认证相关接口")
public class AuthenticationController extends BaseController {

    private final AuthenticationService authenticationService;
    private final UserManagementService userManagementService;
    private final VerificationCodeService verificationCodeService;

    /**
     * 用户登录接口 (需要验证码)
     */
    @Log(description = "用户登录", operationType = OperationTypeEnum.LOGIN)
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "使用邮箱和密码登录，需要验证码")
    public Result<UserVO> login(@Valid @RequestBody LoginDTO loginDTO) {
        logOperation("用户登录", loginDTO.getUsername());
        
        try {
            Result<UserVO> result = authenticationService.login(loginDTO);
            
            if (result.isSuccess()) {
                logSuccess("用户登录", result.getData().getUsername());
            } else {
                logFailure("用户登录", result.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            logFailure("用户登录", e.getMessage());
            throw e;
        }
    }

    /**
     * 简单用户登录接口 (仅用于测试，不需要验证码)
     */
    @Log(description = "简单用户登录", operationType = OperationTypeEnum.LOGIN)
    @PostMapping("/simple-login")
    @Operation(summary = "简单用户登录", description = "使用用户名和密码登录，测试用，不需要验证码")
    public Result<UserVO> simpleLogin(@Valid @RequestBody SimpleLoginDTO simpleLoginDTO) {
        logOperation("简单用户登录", simpleLoginDTO.getUsername());
        
        try {
            Result<UserVO> result = authenticationService.simpleLogin(simpleLoginDTO);
            
            if (result.isSuccess()) {
                logSuccess("简单用户登录", result.getData().getUsername());
            } else {
                logFailure("简单用户登录", result.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            logFailure("简单用户登录", e.getMessage());
            throw e;
        }
    }

    /**
     * 管理员登录接口
     */
    @Log(description = "管理员登录", operationType = OperationTypeEnum.LOGIN)
    @PostMapping("/admin-login")
    @Operation(summary = "管理员登录", description = "管理员专用登录接口")
    public Result<UserVO> adminLogin(@Valid @RequestBody AdminLoginDTO adminLoginDTO) {
        logOperation("管理员登录", adminLoginDTO.getUsername());
        
        try {
            Result<UserVO> result = authenticationService.adminLogin(adminLoginDTO);
            
            if (result.isSuccess()) {
                logSuccess("管理员登录", result.getData().getUsername());
            } else {
                logFailure("管理员登录", result.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            logFailure("管理员登录", e.getMessage());
            throw e;
        }
    }

    /**
     * 用户注册接口
     */
    @Log(description = "用户注册", operationType = OperationTypeEnum.ADD)
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户注册，需要邮箱验证码")
    public Result<UserVO> register(@Valid @RequestBody RegisterDTO registerDTO) {
        logOperation("用户注册", registerDTO.getUsername(), registerDTO.getEmail());

        try {
            // 1. 验证邮箱验证码
            VerificationRequestDTO verifyDto = new VerificationRequestDTO();
            verifyDto.setEmail(registerDTO.getEmail());
            verifyDto.setCode(registerDTO.getCode());
            verifyDto.setType(VerificationCodeType.REGISTRATION.getValue());

            boolean isCodeValid = verificationCodeService.verifyCode(verifyDto);
            if (!isCodeValid) {
                logFailure("用户注册", "验证码无效或已过期");
                return fail(ResultCode.VERIFICATION_CODE_ERROR);
            }

            // 2. 调用用户管理服务进行注册
            Result<UserVO> result = userManagementService.register(registerDTO);
            
            if (result.isSuccess()) {
                logSuccess("用户注册", registerDTO.getUsername());
            } else {
                logFailure("用户注册", result.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            logFailure("用户注册", e.getMessage());
            return fail(ResultCode.SYSTEM_ERROR.getCode(), "注册处理过程中发生错误: " + e.getMessage());
        }
    }

    /**
     * 用户登出接口
     */
    @Log(description = "用户登出", operationType = OperationTypeEnum.LOGOUT)
    @PostMapping("/logout")
    @Operation(summary = "用户登出", description = "用户登出系统")
    public Result<String> logout() {
        logOperation("用户登出");
        
        // TODO: 实现登出逻辑，如清除token、记录登出日志等
        // 这里可以调用认证服务的登出方法
        
        logSuccess("用户登出", "成功退出");
        return success("成功退出");
    }

    /**
     * 刷新令牌接口
     */
    @Log(description = "刷新令牌", operationType = OperationTypeEnum.UPDATE)
    @PostMapping("/refresh-token")
    @Operation(summary = "刷新令牌", description = "刷新用户访问令牌")
    public Result<String> refreshToken(@RequestHeader("Authorization") String token) {
        logOperation("刷新令牌");
        
        try {
            // 移除 "Bearer " 前缀
            if (token.startsWith("Bearer ")) {
                token = token.substring(7);
            }
            
            String newToken = authenticationService.refreshToken(token);
            if (newToken != null) {
                logSuccess("刷新令牌", "令牌刷新成功");
                return success(newToken);
            } else {
                logFailure("刷新令牌", "令牌刷新失败");
                return fail(ResultCode.INVALID_CREDENTIALS);
            }
        } catch (Exception e) {
            logFailure("刷新令牌", e.getMessage());
            throw e;
        }
    }

    /**
     * 验证令牌接口
     */
    @Log(description = "验证令牌", operationType = OperationTypeEnum.QUERY)
    @PostMapping("/validate-token")
    @Operation(summary = "验证令牌", description = "验证访问令牌是否有效")
    public Result<Boolean> validateToken(@RequestHeader("Authorization") String token) {
        logOperation("验证令牌");
        
        try {
            // 移除 "Bearer " 前缀
            if (token.startsWith("Bearer ")) {
                token = token.substring(7);
            }
            
            boolean isValid = authenticationService.validateToken(token);
            logSuccess("验证令牌", isValid ? "令牌有效" : "令牌无效");
            return success(isValid);
        } catch (Exception e) {
            logFailure("验证令牌", e.getMessage());
            return success(false);
        }
    }
}
